/*! ******************************************************************************
 *
 * Created on 2021年9月25日
 *
 * Copyright(c) YuZhou Big Data Laboratory CO.,Ltd, 2022.  All rights reserved.
 *
 *******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/
package org.eclipse.swt.widgets;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FormData;
import org.pentaho.di.core.plugins.JobEntryPluginType;
import org.pentaho.di.core.plugins.StepPluginType;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.ui.core.gui.GUIResource;
import org.pentaho.di.ui.spoon.Spoon;
import org.pentaho.di.ui.spoon.navigation.design.classification.Classification;
import org.pentaho.di.ui.spoon.navigation.design.classification.ClassificationAddShell;
import org.pentaho.di.ui.spoon.navigation.design.classification.category.CategoryAddShell;
import org.yzbdl.lanius.core.plugins.metastore.LdrClassificationEntity;
import org.yzbdl.lanius.core.plugins.service.CategoryService;
import org.yzbdl.lanius.core.plugins.service.ClassificationService;

/**
 * @author tanpeng@yzbdl.ac.cn
 * @version 1.0
 * @date 2022-08-02 11:19
 */
public class LaniusClassExpandBar extends ExpandBar {

    private static Class<?> PKG = Spoon.class;

    private Spoon spoon;

    private ClassificationAddShell classificationAddShell = new ClassificationAddShell();

    private ClassificationService classificationService = ClassificationService.getInstance();

    private CategoryAddShell categoryAddShell = CategoryAddShell.getInstance();

    private CategoryService categoryService = CategoryService.getInstance();

    public LaniusClassExpandBar(Spoon spoon, int style, FormData layout) {
        super(spoon.getLeftTreeComposite(), style);
        this.spoon = spoon;
        this.setLayoutData(layout);
        this.setBackground(GUIResource.getInstance().getColorWhite());

        this.addExpandListener(new LaniusExpandBarExpandListener());
        this.addControlListener(new LaniusExpandBarControlListener());
        this.addMenuDetectListener(new LaniusExpandBarMenuDetectListener());
    }

    public ExpandItem getFocusItem() {
        return this.focusItem;
    }

    @Override
    public LaniusClassExpandItem[] getItems() {
        checkWidget();
        LaniusClassExpandItem[] result = new LaniusClassExpandItem[itemCount];
        System.arraycopy(items, 0, result, 0, itemCount);
        return result;
    }

    /**
     * 监听expandBar展开事件
     * 
     * @author hs@yzbdl.ac.cn
     *
     */
    class LaniusExpandBarExpandListener implements ExpandListener {

        @Override
        public void itemExpanded(ExpandEvent e) {
            LaniusClassExpandItem item = (LaniusClassExpandItem)e.item;
            classificationService.collapseClassification(new Integer[] {});
            LdrClassificationEntity ldrClassificationEntity = item.getClassificationEntity();
            classificationService.expandClassification(ldrClassificationEntity.getId());

            for (ExpandItem i : LaniusClassExpandBar.this.getItems()) {
                if (i != item) {
                    i.setExpanded(false);
                }
            }

            // item的高度== expanbar的高度- item的HeaderHeight - spacing的距离
            item.setHeight(
                LaniusClassExpandBar.this.getSize().y - (LaniusClassExpandBar.this.getItems().length) * item.getHeaderHeight()
                    - (LaniusClassExpandBar.this.getItems().length) * LaniusClassExpandBar.this.getSpacing() - 4);
        }

        @Override
        public void itemCollapsed(ExpandEvent e) {
            LaniusClassExpandItem item = (LaniusClassExpandItem)e.item;
            LdrClassificationEntity ldrClassificationEntity = item.getClassificationEntity();
            classificationService.collapseClassification(ldrClassificationEntity.getId());
        }

    }

    /**
     * 监听expandBar的窗口控制事件，实现随着窗口的改变，实现组件大小的改变
     * 
     * @author hs@yzbdl.ac.cn
     *
     */
    class LaniusExpandBarControlListener implements ControlListener {

        @Override
        public void controlMoved(ControlEvent e) {}

        @Override
        public void controlResized(ControlEvent e) {
            for (ExpandItem item : LaniusClassExpandBar.this.getItems()) {
                if (item.getExpanded()) {
                    // item的高度== expanbar的高度- item的HeaderHeight - spacing的距离
                    item.setHeight(LaniusClassExpandBar.this.getSize().y
                        - (LaniusClassExpandBar.this.getItems().length) * item.getHeaderHeight()
                        - (LaniusClassExpandBar.this.getItems().length) * LaniusClassExpandBar.this.getSpacing() - 4);
                }
            }
        }

    }

    /**
     * 监听鼠标右键
     * 
     * @author hs@yzbdl.ac.cn
     *
     */
    class LaniusExpandBarMenuDetectListener implements MenuDetectListener {

        @Override
        public void menuDetected(MenuDetectEvent e) {
            // 鼠标相对于expandBar的x坐标
            int rX = e.x - spoon.getShell().toDisplay(LaniusClassExpandBar.this.getLocation()).x;
            // 鼠标相对于expandBar的y坐标
            int rY = e.y - spoon.getShell().toDisplay(LaniusClassExpandBar.this.getLocation()).y - 10;
            // 栏目分类数组
            ExpandItem[] items = LaniusClassExpandBar.this.getItems();
            // 搜索鼠标点击节点
            LaniusClassExpandItem itemNow = searchNowItem(items, rX, rY);
            if (itemNow != null) {
                // 当前节点名字
                String itemName = itemNow.getText();

                // 如果当前分组为常用、默认、云端则不做操作
                if (itemName.equals(Classification.COMMONLY_NAME) || itemName.equals(Classification.DEFAULT_NAME)
                    || itemName.equals(Classification.MARKET_NAME)) {
                    return;
                }

                createItemMenu(itemNow);
            } else {
                // 右击菜单
//                Menu menu = new Menu(spoon.getShell(), SWT.POP_UP);
//                generateAddMenuItem(menu);
//                menu.setVisible(true);
            }
        }

        private LaniusClassExpandItem searchNowItem(ExpandItem[] items, int rX, int rY) {
            // 返回节点
            LaniusClassExpandItem resultItem = null;
            for (ExpandItem tempItem : items) {
                LaniusClassExpandItem item = (LaniusClassExpandItem)tempItem;
                if (item.contain(rX, rY - item.getHeaderHeight())) {
                    resultItem = item;
                    return resultItem;
                }
            }
            return resultItem;
        }

        /**
         * 创建右击菜单（修改、删除）
         *
         * @param item
         */
        private void createItemMenu(LaniusClassExpandItem item) {
            Menu menu = new Menu(spoon.getShell(), SWT.POP_UP);
            // 添加栏目
//            generateAddMenuItem(menu);
            // 修改栏目
            generateModifyMenuItem(menu, item);
            // 删除栏目
            generateDeleteMenuItem(menu, item);
            // 添加分组
            generateGroupMenuItem(menu, item);
        }

        /**
         * 修改分组菜单项
         *
         * @param menu
         */
        private void generateModifyMenuItem(Menu menu, LaniusClassExpandItem item) {
            // 修改菜单项
            MenuItem menuItemModify = new MenuItem(menu, SWT.PUSH);
            menuItemModify.setText(BaseMessages.getString(PKG, "Classification.Shell.Modify"));
            // 修改菜单项监听器
            menuItemModify.addSelectionListener(new SelectionAdapter() {

                @Override
                public void widgetSelected(SelectionEvent selectionEvent) {
                    super.widgetSelected(selectionEvent);
                    // 修改窗口
                    Shell shellModify =
                        new Shell(spoon.getShell(), SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.ON_TOP);
                    shellModify.setBounds(520, 265, 260, 100);
                    shellModify.open();
                    shellModify.setImage(GUIResource.getInstance().getImageShellTitle());
                    shellModify.setText(BaseMessages.getString(PKG, "Classification.Shell.Modify"));
                    // 修改文本框
                    Text text = new Text(shellModify, SWT.BORDER | SWT.CENTER);
                    text.setText(item.getText());
                    text.setBounds(10, 10, 130, 25);
                    // 确认按钮
                    Button uttonOk = new Button(shellModify, SWT.PUSH | SWT.CENTER);
                    uttonOk.setBounds(150, 10, 82, 25);
                    uttonOk.setText(BaseMessages.getString(PKG, "System.Button.OK"));
                    // 确认按钮监听器
                    uttonOk.addSelectionListener(new SelectionAdapter() {

                        /**
                         * 修改分组名称并销毁当前窗口
                         *
                         * @param e
                         */
                        @Override
                        public void widgetSelected(SelectionEvent e) {
                            item.setText(text.getText());

                            LdrClassificationEntity entity = item.getClassificationEntity();
                            entity.setName(text.getText());
                            classificationService.update(entity);

                            shellModify.dispose();
                        }
                    });
                }
            });
        }

        /**
         * 修改分组菜单项
         *
         * @param menu
         */
        private void generateDeleteMenuItem(Menu menu, LaniusClassExpandItem item) {
            MenuItem menuItemDelete = new MenuItem(menu, SWT.PUSH);
            menuItemDelete.setText(BaseMessages.getString(PKG, "Classification.Shell.Delete"));
            menu.setVisible(true);

            // 删除菜单项监听器
            menuItemDelete.addSelectionListener(new SelectionAdapter() {

                @Override
                public void widgetSelected(SelectionEvent selectionEvent) {
                    super.widgetSelected(selectionEvent);
                    // 删除窗口
                    Shell shellDelete =
                        new Shell(spoon.getShell(), SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.ON_TOP);
                    shellDelete.setBounds(520, 265, 230, 110);
                    shellDelete.setSize(320, 180);
                    shellDelete.setImage(GUIResource.getInstance().getImageShellTitle());
                    shellDelete.open();
                    shellDelete.setText(BaseMessages.getString(PKG, "Classification.Shell.Delete"));
                    /**
                     * 提示ui，图标从jface获取
                     */
                    // 提示框Messages对象
                    MessageDialog messageDialog = new MessageDialog(shellDelete, "", (Image)null, "", 3,
                        new String[] {IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL}, 0);
                    // 提示框Image对象
                    Image image = messageDialog.getQuestionImage();
                    // 存储图标的Lable
                    Label labelImage = new Label(shellDelete, SWT.NONE);
                    labelImage.setImage(image);
                    labelImage.setBounds(20, 10, 48, 48);
                    // 文字提示Lable
                    Label label = new Label(shellDelete, SWT.NONE);
                    label.setBounds(80, 25, 150, 30);
                    label.setText(BaseMessages.getString(PKG, "Classification.Info.Delete"));
                    // 确认按钮
                    Button buttonOk = new Button(shellDelete, SWT.PUSH);
                    buttonOk.setText(BaseMessages.getString(PKG, "System.Button.OK"));
                    buttonOk.setBounds(40, 80, 82, 25);
                    // 取消按钮
                    Button buttonCancel = new Button(shellDelete, SWT.PUSH);
                    buttonCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));
                    buttonCancel.setBounds(160, 80, 82, 25);
                    // 确认按钮监听器
                    buttonOk.addSelectionListener(new SelectionAdapter() {

                        /**
                         * 如果分组展开则关闭 销毁分组并销毁当前窗口
                         *
                         * @param selectionEvent
                         */
                        @Override
                        public void widgetSelected(SelectionEvent selectionEvent) {
                            super.widgetSelected(selectionEvent);
                            // 栏目实体
                            LdrClassificationEntity entity = item.getClassificationEntity();
                            classificationService.delete(entity);
                            shellDelete.dispose();
                        }
                    });
                    // 取消按钮监听器
                    buttonCancel.addSelectionListener(new SelectionAdapter() {

                        /**
                         * 销毁当前窗口
                         *
                         * @param selectionEvent
                         */
                        @Override
                        public void widgetSelected(SelectionEvent selectionEvent) {
                            super.widgetSelected(selectionEvent);
                            item.setExpanded(false);
                            shellDelete.dispose();
                        }
                    });
                    shellDelete.addKeyListener(new KeyAdapter() {
                        public void keyPressed(KeyEvent e) {
                            switch (e.character) {
                                case SWT.CR:
                                    LdrClassificationEntity entity = item.getClassificationEntity();
                                    classificationService.delete(entity);
                                    shellDelete.dispose();
                                    break;
                                case SWT.ESC:
                                    item.setExpanded(false);
                                    shellDelete.dispose();
                                    break;
                            }

                        }
                    });
                }
            });
        }

    }

    /**
     * @描述 在栏目下添加分组
     * @data 2020/10/28
     *  * @param menu 菜单
     * @param item 指定的栏目
     * @return void
     */
    private void generateGroupMenuItem(Menu menu, LaniusClassExpandItem item) {
        MenuItem menuItemAdd = new MenuItem(menu, SWT.PUSH);
        menuItemAdd.setText(BaseMessages.getString(PKG, "Classification.Shell.New"));
        menuItemAdd.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent selectionEvent) {
                super.widgetSelected(selectionEvent);
                if (spoon.showTrans) {
                    categoryAddShell.createAddGroupShell(spoon.getShell(), StepPluginType.class, item);
                } else if (spoon.showJob) {
                    categoryAddShell.createAddGroupShell(spoon.getShell(), JobEntryPluginType.class, item);
                }
            }
        });
    }
}
